package cmpe.swe.purcom;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import cmpe.swe.purcom.dao.UserDao;
import cmpe.swe.purcom.model.Community;
import cmpe.swe.purcom.model.FeedItem;
import cmpe.swe.purcom.model.Skill;
import cmpe.swe.purcom.model.User;
import cmpe.swe.purcom.service.CommunityService;
import cmpe.swe.purcom.service.SkillService;
import cmpe.swe.purcom.service.UserService;

/**
 * Handles requests for the application home page.
 */
@Controller
// Comment by Onur Torna.
// Comment by Tongu� �atakl�.
// Comment by Hatip Kabak
// Comment by Oguz Onuk test
public class HomeController {

	private static final String SAVE_DIR = "purcom" + File.separator + "images";

	@Autowired
	private UserService userService;
	@Autowired
	private CommunityService communityService;
	@Autowired
	private UserDao userDao;
	@Autowired
	private SkillService skillService;

	/**
	 * Return home page for the logged in user. If user did not log in, it
	 * returns sign-in page
	 * 
	 * @param locale
	 *            object for spring form element
	 * @param model
	 *            object for spring form element
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user.
	 * @return a web page
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView home(Locale locale, Model model, HttpSession session) {
		// berna erden test
		User sessionUser = (User) session.getAttribute("sessionUser");
		if (sessionUser != null) { // already logged in
			List<Community> myCommunities = communityService
					.getMyCommunities(sessionUser.getId());
			ModelAndView mv = new ModelAndView("home");
			List<FeedItem> fi = communityService.getActivityFeedOfMyCommunities(sessionUser.getId());
			mv.addObject("myCommunities", myCommunities);
			mv.addObject("feedItems", fi);
			return mv;
		} else {
			return new ModelAndView("redirect:signin");
		}
	}

	/**
	 * Returns the home page of the user.
	 * 
	 * @param u
	 *            a User object
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user.
	 * @return a web page
	 */
	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public ModelAndView home(@ModelAttribute("user") User u, HttpSession session) {

		session.setAttribute("sessionUser", u);
		return new ModelAndView("redirect:/");

	}

	/**
	 * Returns home page for logged in user. If user did not log in it return
	 * sign-in page
	 * 
	 * @param model
	 *            object for spring form element
	 * @param command
	 *            object for spring form element
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user.
	 * @return a web page
	 */
	@RequestMapping(value = "/signin", method = RequestMethod.GET)
	public String viewSignin(Model model,
			@ModelAttribute("user") Object command, HttpSession session) {
		User sessionUser = (User) session.getAttribute("sessionUser");
		if (sessionUser != null) { // already logged in
			return "redirect:/";
		} else {
			User u = new User();
			model.addAttribute("user", u);
			return "signin";
		}
	}

	/**
	 * Returns the home page for the user which already logged in. The user's
	 * attributes are set by setAttribute() function in the method If user can
	 * not log in, it return sign-in page
	 * 
	 * @param email
	 *            e-mail of the user taken from html page
	 * @param password
	 *            password of the user taken from html page
	 * @param request
	 *            a HttpServletRequest object is taken from the user
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user.
	 * @return a web page
	 */
	@RequestMapping(value = "/signin", method = RequestMethod.POST)
	public ModelAndView signIn(
			@RequestParam(value = "email", required = true) String email,
			@RequestParam(value = "password", required = true) String password,
			HttpServletRequest request, HttpSession session) {
		if (email.equals("") || password.equals("")) {
			return new ModelAndView("redirect:signin");
		}
		User u = userService.canLogin(email, password);
		if (u != null) {
			session.setAttribute("sessionUser", u);
			return new ModelAndView("redirect:/");
		} else {
			return new ModelAndView("redirect:signin");
		}

	}

	/**
	 * Returns the sign-up page with its attributes for the not logged in user.
	 * If user already logged in it returns home page
	 * 
	 * @param model
	 *            object for spring form element
	 * @param command
	 *            object for spring form element
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user.
	 * @return a web page
	 */
	@RequestMapping(value = "/signup", method = RequestMethod.GET)
	public String viewSignup(Model model,
			@ModelAttribute("user") Object command, HttpSession session) {
		User sessionUser = (User) session.getAttribute("sessionUser");
		if (sessionUser != null) { // already logged in
			return "redirect:/";
		} else {
			User u = new User();
			List<Skill> skills = skillService.getSkills();
			model.addAttribute("user", u);
			model.addAttribute("skills", skills);
			return "signup";
		}
	}

	/**
	 * Set the properties of the created User object and returns the home page.
	 * If there is an exception it returns sign-up page
	 * 
	 * @param u
	 *            a User object which is created
	 * @param request
	 *            a HttpServletRequest object is taken from the user
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user.
	 * @return a web page
	 */
	@RequestMapping(value = "/signup", method = RequestMethod.POST)
	public String signUp(@ModelAttribute("user") User u,
			MultipartHttpServletRequest request, HttpSession session) {
		try {
			MultipartFile mpf = request.getFile("profilePic");
			byte[] bytes = mpf.getBytes();

			// Creating the directory to store file
			String rootPath = System.getProperty("catalina.home");
			File dir = new File(rootPath + File.separator + SAVE_DIR);
			if (!dir.exists())
				dir.mkdirs();

			// Create the file on server
			String fileName = UUID.randomUUID().toString();
			File serverFile = new File(dir.getAbsolutePath() + File.separator
					+ fileName);
			BufferedOutputStream stream = new BufferedOutputStream(
					new FileOutputStream(serverFile));
			stream.write(bytes);
			stream.close();

			u.setProfilePicLoc(fileName);
			// TODO create skill which don't exist
			if (u.getEmail().equals("") || u.getPassword().equals("")
					|| u.getName().equals("") || u.getSurname().equals("")) {
				return "redirect:signup";
			}
			userService.createUserWithSkills(u);
			session.setAttribute("sessionUser", u);

			return "redirect:/";
		} catch (Exception e) {
			return "redirect:signup";
		}
	}

	/**
	 * Returns the home age after the user is signed out.
	 * 
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user.
	 * @return a web page
	 * @throws IOException
	 *             handles I/O exceptions
	 */
	@RequestMapping(value = "/signout", method = RequestMethod.GET)
	public String signOut(HttpSession session) throws IOException {
		session.setAttribute("sessionUser", null);
		return "redirect:/";
	}

	/**
	 * Returns the profile  page after the user is signed out.
	 * 
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user.
	 * @return a web page
	 * @throws IOException
	 *             handles I/O exceptions
	 */
	
	@RequestMapping(value = "/profilepage", method = RequestMethod.GET)
	public String profilePage(HttpSession session) throws IOException {
		User u = (User) session.getAttribute("sessionUser");
		if (u == null) {
			return "redirect:/";
		}
		return "profilepage";
	}
	/**
	 * 
	 * @param pfm
	 *            String attribute for path configuration
	 * @return
	 */
	@RequestMapping(produces = MediaType.IMAGE_PNG_VALUE, value = "/img/{pictureFileName}", method = RequestMethod.GET)
	public HttpEntity<byte[]> getPicture(
			@PathVariable("pictureFileName") String pfm) {
		String exactPath = System.getProperty("catalina.home") + File.separator
				+ SAVE_DIR + File.separator + pfm;
		File f = new File(exactPath);
		try {
			BufferedInputStream bs = new BufferedInputStream(
					new FileInputStream(f));
			byte[] b = new byte[10000000];
			bs.read(b);
			bs.close();
			return new HttpEntity<byte[]>(b);
		} catch (Exception e) {
			e.printStackTrace();
			return new HttpEntity<byte[]>("fak".getBytes());
		}

	}

	/**
	 * Just for testing json request and response with map object
	 * 
	 * @param t
	 * @return
	 */
	@RequestMapping(value = "/test", method = RequestMethod.POST)
	public @ResponseBody
	Map<String, Object> test(@RequestBody Map<String, Object> t) {
		Map<String, Object> mv = new HashMap<String, Object>();
		mv.put("reqSc", t.get("success"));
		mv.put("reqSt", t.get("stuff"));
		return mv;
	}

}